﻿using System.Collections;
using System.Windows.Controls;
using System.Windows.Markup;

namespace DimensionsHelper.Client.Controls;

public class BorderGridRangeCollection : IList, IAddChild
{
    private readonly WeakReference<BorderGrid> _grid;
    private readonly List<BorderGridRange> _ranges = [];
    private BorderGridCellMatrix _cellMatrix;
    private bool _isInitialized;

    internal BorderGridRangeCollection(BorderGrid grid)
    {
        _grid = new WeakReference<BorderGrid>(grid);
        _cellMatrix = new BorderGridCellMatrix(_grid, 0, 0);
    }


    public int Rows { get; private set; }

    public int Columns { get; private set; }

    public int CellsCount => Rows * Columns;

    private BorderGrid Grid
    {
        get
        {
            if (_grid.TryGetTarget(out BorderGrid? grid))
            {
                return grid;
            }

            throw new InvalidOperationException();
        }
    }


    public void AddChild(object value)
    {
        if (value is BorderGridRange range)
        {
            range.Collection = this;
            _ranges.Add(range);
        }
        else
        {
            throw new ArgumentException($@"'value' is not a type of '{nameof(BorderGridRange)}'", nameof(value));
        }
    }


    public void AddText(string text)
    {
        throw new NotSupportedException();
    }


    public bool IsFixedSize => false;

    public bool IsReadOnly => false;

    public int Count => _ranges.Count;

    public bool IsSynchronized => false;

    public object SyncRoot => throw new NotSupportedException();

    public object? this[int index]
    {
        get => _ranges[index];

        set
        {
            if (value is BorderGridRange range)
            {
                _ranges[index] = range;
            }
        }
    }


    public int Add(object? value)
    {
        if (value is BorderGridRange range)
        {
            range.Collection = this;
            _ranges.Add(range);
            return Count - 1;
        }

        return -1;
    }


    public void Clear()
    {
        _ranges.Clear();
    }

    public bool Contains(object? value)
    {
        return _ranges.Contains(value);
    }

    public int IndexOf(object? value)
    {
        if (value is BorderGridRange range)
        {
            return _ranges.IndexOf(range);
        }

        return -1;
    }

    public void Insert(int index, object? value)
    {
        if (value is BorderGridRange range)
        {
            _ranges.Insert(index, range);
        }
    }

    public void Remove(object? value)
    {
        if (value is BorderGridRange range)
        {
            _ranges.Remove(range);
        }
    }

    public void RemoveAt(int index)
    {
        if (index >= 0 && index < Count)
        {
            _ranges.RemoveAt(index);
        }
    }

    public void CopyTo(Array array, int index)
    {
        _ranges.CopyTo((BorderGridRange[])array, index);
    }

    public IEnumerator GetEnumerator()
    {
        return _ranges.GetEnumerator();
    }

    public void InvalidateVisual()
    {
        if (_grid.TryGetTarget(out BorderGrid? grid))
        {
            grid.InvalidateVisual();
        }
    }


    internal BorderGridCell GetCell(int index)
    {
        return _cellMatrix[index];
    }


    internal void Initialize(BorderGrid grid)
    {
        if (_isInitialized)
        {
            return;
        }

        int rows = grid.RowDefinitions.Count;
        int cols = grid.ColumnDefinitions.Count;

        Rows = rows;
        Columns = cols;

        // 如果未定义行或列，添加至少一列
        rows = Math.Max(1, rows);
        cols = Math.Max(1, cols);

        _cellMatrix = new BorderGridCellMatrix(_grid, rows, cols);
        // 添加边框
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                BorderGridCell cell = _cellMatrix[r, c];

                if (r > 0)
                {
                    BorderGridCell topNode = _cellMatrix[r - 1, c];
                    topNode.Bottom = cell;
                    cell.Top = topNode;
                }

                if (c > 0)
                {
                    BorderGridCell leftNode = _cellMatrix[r, c - 1];
                    leftNode.Right = cell;
                    cell.Left = leftNode;
                }

                if (r == rows - 1)
                {
                    cell.AddFlags(BorderCellFlags.BottomBound);
                }

                if (c == cols - 1)
                {
                    cell.AddFlags(BorderCellFlags.RightBound);
                }
            }
        }

        // 更新区间
        foreach (BorderGridRange child in _ranges)
        {
            child.Initialize(_cellMatrix);
        }

        _isInitialized = true;
    }


    internal void UpdateBorder()
    {
        InvalidateVisual();

        for (int r = 0; r < Rows; r++)
        {
            for (int c = 0; c < Columns; c++)
            {
                _cellMatrix[r, c].UpdateBorder();
            }
        }
    }


    public double GetRowOffset(int row)
    {
        return Grid.RowDefinitions[row].Offset;
    }


    public double GetColumnOffset(int column)
    {
        return Grid.ColumnDefinitions[column].Offset;
    }


    public double GetRowEndOffset(int row)
    {
        RowDefinition? rowDef = Grid.RowDefinitions[row];
        return rowDef.Offset + rowDef.ActualHeight;
    }


    public double GetColumnEndOffset(int column)
    {
        ColumnDefinition? colDef = Grid.ColumnDefinitions[column];
        return colDef.Offset + colDef.ActualWidth;
    }


    public double GetRowHeight(int row)
    {
        return Grid.RowDefinitions[row].ActualHeight;
    }


    public double GetColumnWidth(int column)
    {
        return Grid.ColumnDefinitions[column].ActualWidth;
    }
}